#include <sxCamera_Archetype.h>

const Sx::Math::Projection DEFAULT_PROJECTION = Sx::Math::PERSPECTIVE;
const Sx::Math::Perspective DEFAULT_PERSPECTIVE = Sx::Math::THIRD_PERSON;

using Sx::Graphics::Objects::Camera;
using Sx::Graphics::GeometricRepresentation;

Sx::Graphics::Archetypes::Objects::Camera_Archetype::Camera_Archetype(const std::shared_ptr<RendererImplementation>& renderer) : 
	GeometricObject_Archetype(std::make_shared<Camera>(DEFAULT_PROJECTION, DEFAULT_PERSPECTIVE), renderer, std::make_shared<GeometricRepresentation>()) {}

Sx::Graphics::Archetypes::Objects::Camera_Archetype::Camera_Archetype(Math::View view, const std::shared_ptr<RendererImplementation>& renderer) : 
	GeometricObject_Archetype(std::make_shared<Camera>(Math::ORTHOGRAPHIC, DEFAULT_PERSPECTIVE), renderer, std::make_shared<GeometricRepresentation>()) {
	this->object->setView(view);
}

Sx::Graphics::Archetypes::Objects::Camera_Archetype::Camera_Archetype(Math::Perspective perspective, const std::shared_ptr<RendererImplementation>& renderer) : 
	GeometricObject_Archetype(std::make_shared<Camera>(Math::PERSPECTIVE, perspective), renderer, std::make_shared<GeometricRepresentation>()) {}

Sx::Graphics::Archetypes::Objects::Camera_Archetype::Camera_Archetype(Math::Projection projection, Math::Perspective perspective, const std::shared_ptr<RendererImplementation>& renderer) : 
	GeometricObject_Archetype(std::make_shared<Camera>(projection, perspective), renderer, std::make_shared<GeometricRepresentation>()) {}

Sx::Graphics::Archetypes::Objects::Camera_Archetype::~Camera_Archetype() {}

bool Sx::Graphics::Archetypes::Objects::Camera_Archetype::pick(const Eigen::Vector3f& pickSegmentStart, const Eigen::Vector3f& pickSegmentEnd, Eigen::Vector3f& intersectionPoint) {
	return false;
}

bool Sx::Graphics::Archetypes::Objects::Camera_Archetype::intersect(const Eigen::Vector3f& segment_p0, const Eigen::Vector3f& segment_p1, Eigen::Vector3f& intersectionPoint) {
	return false;
}

bool Sx::Graphics::Archetypes::Objects::Camera_Archetype::setPosition(float x, float y, float z) {
	if ( this->object == nullptr ) return false;
	if ( this->physicalRepresentation == nullptr ) return false;

	//--------------------------------------------------------------------------
	// Set the position of the abstract camera object.
	//--------------------------------------------------------------------------
	this->object->setPosition(x, y, z);

	//--------------------------------------------------------------------------
	// If the physical representation doesn't have a position stored then set
	// it to the newly provided position.
	//--------------------------------------------------------------------------
	if ( this->physicalRepresentation->vertices.size() == 0 ) {
		this->physicalRepresentation->vertices.add(Eigen::Vector3f(x, y, z));
	}
	else {
		this->physicalRepresentation->vertices.resize(1);
		this->physicalRepresentation->vertices[0] = Eigen::Vector3f(x, y, z);
	}
	
	return true;
}

bool Sx::Graphics::Archetypes::Objects::Camera_Archetype::setPosition(const Eigen::Vector3f& position) {
	return this->setPosition(position.x(), position.y(), position.z());
}
